package com.hzncc.flowable_diboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.extension.SnowflakeIdGenerator;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.util.JSON;
import com.diboot.core.util.SqlExecutor;
import com.diboot.core.vo.JsonResult;
import com.diboot.iam.entity.IamUser;
import com.dingtalk.api.request.OapiCheckinRecordGetRequest;
import com.dingtalk.api.response.OapiCheckinRecordGetResponse;
import com.hzncc.flowable_diboot.entity.DingAppConfig;
import com.hzncc.flowable_diboot.entity.SalesSignIn;
import com.hzncc.flowable_diboot.mapper.DingAppConfigMapper;
import com.hzncc.flowable_diboot.mapper.SalesSignInMapper;
import com.hzncc.flowable_diboot.service.DingtalkService;
import com.hzncc.flowable_diboot.service.SalesSignInService;
import com.taobao.api.ApiException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 签到 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-06-07
 * Copyright © MyCorp
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SalesSignInServiceImpl extends BaseServiceImpl<SalesSignInMapper, SalesSignIn> implements SalesSignInService {

    private final DingtalkService dingtalkService;
    private final DingAppConfigMapper dingAppConfigMapper;


    @Override
    public void pullCheckInData(long interval) throws Exception {
        // 查询的时间范围 从配置页面的参数中获取‘interval’
        long endTime = System.currentTimeMillis();
        long startTime = endTime - interval;
        JsonResult<String> token = dingtalkService.getToken();
        if (token.getCode() != 0) {
            throw new RuntimeException(token.getMsg());
        }
        String data = token.getData();
        OapiCheckinRecordGetRequest req = new OapiCheckinRecordGetRequest();
        // 获取用户列表查询签到记录
        //List<IamUser> users = iamUserService.getEntityList(new QueryWrapper());
        List<IamUser> users = SqlExecutor.getJdbcTemplate().query("select * from dbt_iam_user where is_deleted = 0", BeanPropertyRowMapper.newInstance(IamUser.class));
        // key usernum value user
        Map<String, List<IamUser>> userMap = new HashMap<>();
        for (IamUser user : users) {
            List<IamUser> userList = userMap.get(user.getDingUserId()) == null ? new ArrayList<>() : userMap.get(user.getDingUserId());
            userList.add(user);
            userMap.put(user.getDingUserId(), userList);
        }
        List<String> userNumList = users.stream().map(IamUser::getDingUserId).distinct().collect(Collectors.toList());
        List<SalesSignIn> records = new ArrayList<>();
        List<String> uids = new ArrayList<>();
        // 签到接口参数
        req.setCursor(0L);
        req.setSize(100L);
        req.setEndTime(endTime);
        req.setStartTime(startTime);
        // 钉钉接口用户列表参数最多10个
        for (int i = 0; i < userNumList.size(); i += 10) {
            // 防止数组越界
            int target = Math.min(i + 10, userNumList.size());
            List<String> userNums = userNumList.subList(i, target);
            uids.addAll(userNums);
            req.setUseridList(String.join(",", uids));
            JsonResult<List<OapiCheckinRecordGetResponse.CheckinRecordVo>> checkInData = dingtalkService.getCheckInData(data, req);
            Map<String, Set<LocalDateTime>> userDateMap = new HashMap<>();
            if (checkInData.getCode() == 0) {
                List<OapiCheckinRecordGetResponse.CheckinRecordVo> list = checkInData.getData();
                for (OapiCheckinRecordGetResponse.CheckinRecordVo recordVo : list) {
                    List<IamUser> userList = userMap.get(recordVo.getUserid());
                    for (IamUser user : userList) {
                        SalesSignIn record = new SalesSignIn();
                        record.setPlace(recordVo.getPlace());
                        record.setUid(user.getId());
                        Date date = new Date(recordVo.getCheckinTime());
                        Instant instant = date.toInstant();
                        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
                        record.setSignInTime(dateTime);
                        record.setTenantId(user.getTenantId());
                        record.setDetailPlace(recordVo.getDetailPlace());
                        record.setRemark(recordVo.getRemark());
                        record.setImgList(JSON.stringify(recordVo.getImageList()));
                        record.setVisitUser(recordVo.getVisitUser());
                        // 去重
                        Set<LocalDateTime> localDateTimes = userDateMap.get(record.getUid()) == null ? new HashSet<>() : userDateMap.get(record.getUid());
                        if (localDateTimes.contains(record.getSignInTime())) {
                            continue;
                        }
                        localDateTimes.add(record.getSignInTime());
                        userDateMap.put(record.getUid(), localDateTimes);
                        records.add(record);
                    }
                }
            } else {
                log.error(checkInData.getMsg());
            }
            uids.clear();
        }
        // 定时任务中 mybatis获取不到security即获取不到用户信息，故使用jdbcTemplate
        JdbcTemplate jdbcTemplate = SqlExecutor.getJdbcTemplate();
        String sql = "insert into mdl_sales_sign_in (id, tenant_id, uid, place, sign_in_time, detail_place, remark, img_list,visit_user,create_time,create_by) values (?,?,?,?,?,?,?,?,?,?,?);";
        List<Object[]> args = new ArrayList<>();
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator();
        for (SalesSignIn record : records) {
            Object[] a = Arrays.asList(generator.generate(record), record.getTenantId(), record.getUid(), record.getPlace(), record.getSignInTime(), record.getDetailPlace(), record.getRemark(), record.getImgList(), record.getVisitUser(), LocalDateTime.now(), "sys").toArray();
            args.add(a);
        }
        jdbcTemplate.batchUpdate(sql, args);
    }

    /**
     * 多钉钉租户租户场景
     *
     * @param interval
     * @throws Exception
     * @author 陈广煜
     * @date 2024-08-29
     */
    public void execute(Long interval) throws Exception {
        List<DingAppConfig> dingAppConfigs = dingAppConfigMapper.selectList(new QueryWrapper<>());
        for (DingAppConfig dingAppConfig : dingAppConfigs) {
            JsonResult<String> token = dingtalkService.getToken(dingAppConfig.getTenant());
            if (token.getCode() == 0) {
                pullCheckInData(token.getData(), interval);
            } else {
                log.error(token.getMsg());
            }
        }
    }

    private void pullCheckInData(String data, Long interval) throws ApiException {
        long endTime = System.currentTimeMillis();
        long startTime = endTime - interval;
        OapiCheckinRecordGetRequest req = new OapiCheckinRecordGetRequest();
        // 获取用户列表查询签到记录
        //List<IamUser> users = iamUserService.getEntityList(new QueryWrapper());
        List<IamUser> users = SqlExecutor.getJdbcTemplate().query("select ding_user_id,tenant_id,id from dbt_iam_user where is_deleted = 0", BeanPropertyRowMapper.newInstance(IamUser.class));
        // key usernum value user
        Map<String, List<IamUser>> userMap = new HashMap<>();
        for (IamUser user : users) {
            List<IamUser> userList = userMap.get(user.getDingUserId()) == null ? new ArrayList<>() : userMap.get(user.getDingUserId());
            userList.add(user);
            userMap.put(user.getDingUserId(), userList);
        }
        List<String> userNumList = users.stream().map(IamUser::getDingUserId).distinct().collect(Collectors.toList());
        List<SalesSignIn> records = new ArrayList<>();
        List<String> uids = new ArrayList<>();
        // 签到接口参数
        req.setCursor(0L);
        req.setSize(100L);
        req.setEndTime(endTime);
        req.setStartTime(startTime);
        // 钉钉接口用户列表参数最多10个
        for (int i = 0; i < userNumList.size(); i += 10) {
            // 防止数组越界
            int target = Math.min(i + 10, userNumList.size());
            List<String> userNums = userNumList.subList(i, target);
            uids.addAll(userNums);
            req.setUseridList(String.join(",", uids));
            JsonResult<List<OapiCheckinRecordGetResponse.CheckinRecordVo>> checkInData = dingtalkService.getCheckInData(data, req);
            Map<String, Set<LocalDateTime>> userDateMap = new HashMap<>();
            if (checkInData.getCode() == 0) {
                List<OapiCheckinRecordGetResponse.CheckinRecordVo> list = checkInData.getData();
                for (OapiCheckinRecordGetResponse.CheckinRecordVo recordVo : list) {
                    List<IamUser> userList = userMap.get(recordVo.getUserid());
                    for (IamUser user : userList) {
                        SalesSignIn record = new SalesSignIn();
                        record.setPlace(recordVo.getPlace());
                        record.setUid(user.getId());
                        Date date = new Date(recordVo.getCheckinTime());
                        Instant instant = date.toInstant();
                        LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
                        record.setSignInTime(dateTime);
                        record.setTenantId(user.getTenantId());
                        record.setDetailPlace(recordVo.getDetailPlace());
                        record.setRemark(recordVo.getRemark());
                        record.setImgList(JSON.stringify(recordVo.getImageList()));
                        record.setVisitUser(recordVo.getVisitUser());
                        // 去重
                        Set<LocalDateTime> localDateTimes = userDateMap.get(record.getUid()) == null ? new HashSet<>() : userDateMap.get(record.getUid());
                        if (localDateTimes.contains(record.getSignInTime())) {
                            continue;
                        }
                        localDateTimes.add(record.getSignInTime());
                        userDateMap.put(record.getUid(), localDateTimes);
                        records.add(record);
                    }
                }
            } else {
                log.error(checkInData.getMsg());
            }
            uids.clear();
        }
        // 定时任务中 mybatis获取不到security即获取不到用户信息，故使用jdbcTemplate
        JdbcTemplate jdbcTemplate = SqlExecutor.getJdbcTemplate();
        String sql = "insert into mdl_sales_sign_in (id, tenant_id, uid, place, sign_in_time, detail_place, remark, img_list,visit_user,create_time,create_by) values (?,?,?,?,?,?,?,?,?,?,?);";
        List<Object[]> args = new ArrayList<>();
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator();
        for (SalesSignIn record : records) {
            Object[] a = Arrays.asList(generator.generate(record), record.getTenantId(), record.getUid(), record.getPlace(), record.getSignInTime(), record.getDetailPlace(), record.getRemark(), record.getImgList(), record.getVisitUser(), LocalDateTime.now(), "sys").toArray();
            args.add(a);
        }
        jdbcTemplate.batchUpdate(sql, args);
    }

}